<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>12 发布订阅1</title>
</head>

<body>
  <button class="btn1">添加订阅</button>
  <button class="btn2">取消订阅fn1 和 fn3</button>
  <button class="btn3">通知执行</button>
  <script>
    const btn1 = document.querySelector(".btn1"),
      btn2 = document.querySelector(".btn2"),
      btn3 = document.querySelector(".btn3");

    const sub = (() => {
      // 创建事件池（关键就是这个结构的设计）
      let pond = {};
      // 结构分析
      // { 
      //   'AAA':[fn1,fn2,...],
      //   'BBB':[fn1,fn2,...]
      // }

      // 订阅/取消订阅/通知执行
      const on = (event, func) => {
        !pond.hasOwnProperty(event) ? pond[event] = [] : null;
        let arr = pond[event];
        !arr.includes(func) ? arr.push(func) : null;
      }
      const off = (event, func) => {
        let arr = pond[event] || [];
        pond[event] = arr.filter(item => item !== func);
      }
      const emit = (event, ...params) => {
        let arr = pond[event] || [];
        arr.forEach(item => item(...params));
      }

      return { on, off, emit }
    })();

    let fn1 = (x, y) => console.log('fn1', x, y);
    let fn2 = () => {
      console.log('fn2')
      sub.off(fn1);
      sub.off(fn2);
    };
    let fn3 = () => console.log('fn3');
    let fn4 = () => console.log('fn4');
    let fn5 = (x, y) => console.log('fn5', x, y);


    // 测试（事件定时器）
    sub.on("SetTimeout", fn1);
    sub.on("SetTimeout", fn3);

    setTimeout(() => {
      sub.emit("SetTimeout", 20, 20);
    }, 1000)

    // ---------两者互补干扰--------------

    // 测试（事件绑定方式）
    btn1.addEventListener("click", function () {
      sub.on("BTN-CLICK", fn1);
      sub.on("BTN-CLICK", fn2);
      sub.on("BTN-CLICK", fn3);
      sub.on("BTN-CLICK", fn4);
      sub.on("BTN-CLICK", fn5);
    })
    btn2.addEventListener("click", function () {
      sub.off("BTN-CLICK", fn1);
      sub.off("BTN-CLICK", fn3);
    })
    btn3.addEventListener("click", function () {
      sub.emit("BTN-CLICK", 10, 20);
    })
  </script>
</body>

</html>